@skrr-ai/cli 0.1.42 → 0.1.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base-command.d.ts +2 -0
- package/dist/base-command.js +1 -0
- package/dist/commands/balance/index.js +1 -1
- package/dist/commands/balance/overage.js +4 -3
- package/dist/commands/balance/plan.js +10 -6
- package/dist/commands/balance/show.d.ts +32 -0
- package/dist/commands/balance/show.js +74 -3
- package/dist/commands/balance/usage/events.js +3 -2
- package/dist/commands/balance/usage.js +2 -1
- package/dist/commands/browser/install.js +3 -2
- package/dist/commands/browser/uninstall.js +3 -2
- package/dist/commands/code/handover.d.ts +1 -0
- package/dist/commands/code/handover.js +4 -0
- package/dist/commands/code/install.js +3 -2
- package/dist/commands/code/jobs/run.d.ts +1 -0
- package/dist/commands/code/jobs/run.js +4 -0
- package/dist/commands/daemon/install.js +7 -0
- package/dist/commands/harnesses/install.d.ts +11 -0
- package/dist/commands/harnesses/install.js +33 -14
- package/dist/commands/harnesses/installers.d.ts +10 -0
- package/dist/commands/harnesses/installers.js +31 -0
- package/dist/commands/harnesses/leases/show.js +14 -0
- package/dist/commands/harnesses/list.js +3 -2
- package/dist/commands/instructions/install.d.ts +22 -0
- package/dist/commands/instructions/install.js +83 -7
- package/dist/commands/instructions/list.js +5 -0
- package/dist/commands/instructions/show.d.ts +6 -0
- package/dist/commands/instructions/show.js +34 -1
- package/dist/commands/instructions/status.js +17 -1
- package/dist/commands/payments/wallet.js +2 -2
- package/dist/commands/tasks/attachments/set-role.d.ts +24 -0
- package/dist/commands/tasks/attachments/set-role.js +60 -0
- package/dist/commands/tasks/attachments/upload.d.ts +1 -0
- package/dist/commands/tasks/attachments/upload.js +18 -52
- package/dist/commands/tasks/comments/add.d.ts +1 -0
- package/dist/commands/tasks/comments/add.js +67 -2
- package/dist/commands/tasks/complete.d.ts +1 -0
- package/dist/commands/tasks/complete.js +56 -1
- package/dist/commands/tasks/create.d.ts +6 -0
- package/dist/commands/tasks/create.js +26 -3
- package/dist/commands/tasks/labels/attach.js +4 -0
- package/dist/commands/tasks/list.d.ts +1 -0
- package/dist/commands/tasks/list.js +9 -0
- package/dist/commands/tasks/result/submit.d.ts +3 -0
- package/dist/commands/tasks/result/submit.js +76 -8
- package/dist/commands/tasks/show.d.ts +23 -0
- package/dist/commands/tasks/show.js +61 -1
- package/dist/commands/tasks/update.js +16 -2
- package/dist/commands/tasks/updates/add.d.ts +1 -0
- package/dist/commands/tasks/updates/add.js +63 -0
- package/dist/commands/views/create.js +12 -2
- package/dist/commands/views/list.js +3 -2
- package/dist/commands/views/show.js +2 -0
- package/dist/lib/agentic-stream.d.ts +10 -4
- package/dist/lib/agentic-stream.js +25 -11
- package/dist/lib/api-fetch.js +7 -2
- package/dist/lib/cli-installers.d.ts +23 -4
- package/dist/lib/cli-installers.js +56 -8
- package/dist/lib/daemon-setup.d.ts +18 -1
- package/dist/lib/daemon-setup.js +33 -1
- package/dist/lib/dedicated-machines.js +4 -2
- package/dist/lib/file-mime.js +1 -1
- package/dist/lib/first-party-harness-agent.d.ts +16 -1
- package/dist/lib/first-party-harness-agent.js +47 -17
- package/dist/lib/first-party-harness-doctor.js +49 -48
- package/dist/lib/first-party-harness-managed.d.ts +9 -4
- package/dist/lib/first-party-harness-managed.js +13 -10
- package/dist/lib/first-party-harness.d.ts +32 -21
- package/dist/lib/first-party-harness.js +49 -31
- package/dist/lib/harness-provider-input.d.ts +18 -12
- package/dist/lib/harness-provider-input.js +18 -12
- package/dist/lib/harness-tiers.d.ts +4 -3
- package/dist/lib/harness-tiers.js +4 -3
- package/dist/lib/harnesses.d.ts +6 -0
- package/dist/lib/html-text.js +25 -0
- package/dist/lib/instruction-input.d.ts +21 -0
- package/dist/lib/instruction-input.js +30 -0
- package/dist/lib/instruction-provenance.d.ts +54 -0
- package/dist/lib/instruction-provenance.js +84 -0
- package/dist/lib/session-task-endpoints.d.ts +1 -1
- package/dist/lib/session-task-endpoints.js +3 -0
- package/dist/lib/task-asset-upload.d.ts +84 -0
- package/dist/lib/task-asset-upload.js +374 -0
- package/dist/lib/task-closure.d.ts +15 -0
- package/dist/lib/task-closure.js +20 -0
- package/dist/lib/task-view-render.d.ts +14 -0
- package/dist/lib/task-view-render.js +55 -0
- package/dist/lib/tasks.d.ts +26 -0
- package/dist/lib/tasks.js +38 -1
- package/dist/lib/views/vocabulary.d.ts +1 -1
- package/dist/lib/views/vocabulary.js +3 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarness.d.ts +183 -58
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarness.js +286 -100
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessChannels.d.ts +21 -33
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessChannels.js +24 -50
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessHome.d.ts +19 -7
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessHome.js +26 -10
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessTrust.d.ts +9 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessTrust.js +9 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +1 -13
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/legacyStatePreflight.d.ts +21 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/legacyStatePreflight.js +75 -19
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarness.d.ts +183 -58
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarness.js +279 -99
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessChannels.d.ts +21 -33
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessChannels.js +24 -49
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessHome.d.ts +19 -7
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessHome.js +27 -11
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessTrust.d.ts +9 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessTrust.js +9 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +1 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/legacyStatePreflight.d.ts +21 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/legacyStatePreflight.js +74 -19
- package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +4588 -4509
- package/dist/node_modules/@skrr-ai/data-provider/package.json +1 -1
- package/oclif.manifest.json +33980 -33832
- package/package.json +3 -3
package/dist/base-command.d.ts
CHANGED
|
@@ -346,6 +346,8 @@ export declare function parseGlobalFlags(argv: readonly string[]): ParsedGlobals
|
|
|
346
346
|
export declare function apiRefusal(err: unknown): {
|
|
347
347
|
code?: string;
|
|
348
348
|
message?: string;
|
|
349
|
+
/** The parsed JSON body, for a refusal that carries structured context. */
|
|
350
|
+
body?: Record<string, unknown>;
|
|
349
351
|
};
|
|
350
352
|
/**
|
|
351
353
|
* Prefix a failure message with the resource it is about.
|
package/dist/base-command.js
CHANGED
|
@@ -18,7 +18,7 @@ const show_1 = __importDefault(require("./show"));
|
|
|
18
18
|
* lists every subcommand, which is where a menu belongs.
|
|
19
19
|
*/
|
|
20
20
|
class Balance extends show_1.default {
|
|
21
|
-
static description = 'Show your hosted usage balance — the
|
|
21
|
+
static description = 'Show your hosted usage balance and plan limits — the ceilings that refuse a turn (not the x402 wallet). ' +
|
|
22
22
|
'See `balance usage`, `balance overage`, `balance statement` and `balance history` for the detail behind it.';
|
|
23
23
|
static examples = [
|
|
24
24
|
'<%= config.bin %> balance',
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
|
+
const auth_core_1 = require("@skrr-ai/auth-core");
|
|
4
5
|
const base_command_1 = require("../../base-command");
|
|
5
6
|
const balance_1 = require("../../lib/balance");
|
|
6
7
|
class BalanceOverage extends base_command_1.BaseCommand {
|
|
7
|
-
static description =
|
|
8
|
+
static description = `Enable or disable personal ${auth_core_1.FIRST_PARTY_HARNESS.displayName} overage after included allowance is exhausted`;
|
|
8
9
|
static examples = [
|
|
9
10
|
'<%= config.bin %> balance overage enabled',
|
|
10
11
|
'<%= config.bin %> balance overage disabled',
|
|
@@ -12,7 +13,7 @@ class BalanceOverage extends base_command_1.BaseCommand {
|
|
|
12
13
|
];
|
|
13
14
|
static args = {
|
|
14
15
|
state: core_1.Args.string({
|
|
15
|
-
description:
|
|
16
|
+
description: `Whether personal stored balance may pay for ${auth_core_1.FIRST_PARTY_HARNESS.displayName} overage`,
|
|
16
17
|
required: true,
|
|
17
18
|
options: ['enabled', 'disabled'],
|
|
18
19
|
ignoreStdin: true,
|
|
@@ -34,7 +35,7 @@ class BalanceOverage extends base_command_1.BaseCommand {
|
|
|
34
35
|
this.log(JSON.stringify({ ownerType: 'user', overageEnabled: result?.enabled === true }, null, 2));
|
|
35
36
|
return;
|
|
36
37
|
}
|
|
37
|
-
this.log(
|
|
38
|
+
this.log(`${auth_core_1.FIRST_PARTY_HARNESS.displayName} overage ${result?.enabled ? 'enabled' : 'disabled'} for your personal billing account.`);
|
|
38
39
|
this.log(result?.enabled
|
|
39
40
|
? 'New admissions may use stored balance after included allowance is exhausted.'
|
|
40
41
|
: 'New admissions will stop when included allowance is exhausted.');
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.renderSkyCodePlan = renderSkyCodePlan;
|
|
4
4
|
const core_1 = require("@oclif/core");
|
|
5
|
+
const auth_core_1 = require("@skrr-ai/auth-core");
|
|
5
6
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
6
7
|
const base_command_1 = require("../../base-command");
|
|
7
8
|
const balance_1 = require("../../lib/balance");
|
|
8
9
|
const web_url_1 = require("../../lib/web-url");
|
|
9
10
|
class BalancePlan extends base_command_1.BaseCommand {
|
|
10
|
-
static description =
|
|
11
|
+
static description = `Show your ${auth_core_1.FIRST_PARTY_HARNESS.displayName} plan, renewal state, available tiers, and the matching lifecycle page`;
|
|
11
12
|
static examples = [
|
|
12
13
|
'<%= config.bin %> balance plan',
|
|
13
14
|
'<%= config.bin %> balance plan --json',
|
|
@@ -33,7 +34,7 @@ class BalancePlan extends base_command_1.BaseCommand {
|
|
|
33
34
|
}
|
|
34
35
|
exports.default = BalancePlan;
|
|
35
36
|
function renderSkyCodePlan(subscription, lifecycleUrl, log) {
|
|
36
|
-
log(
|
|
37
|
+
log(`${auth_core_1.FIRST_PARTY_HARNESS.displayName} plan — ${subscription.tierName}`);
|
|
37
38
|
log(` Status ${subscription.status}`);
|
|
38
39
|
log(` Price $${subscription.monthlyPriceUsd}/month`);
|
|
39
40
|
log(` Current period ${subscription.currentPeriodStart ?? 'not started'}`);
|
|
@@ -43,10 +44,13 @@ function renderSkyCodePlan(subscription, lifecycleUrl, log) {
|
|
|
43
44
|
log(` Concurrent sessions ${subscription.concurrentSessions ?? 'not reported'}`);
|
|
44
45
|
log(` Requests per minute ${subscription.rateLimitPerMin}`);
|
|
45
46
|
log('');
|
|
46
|
-
log(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
log(`Available ${auth_core_1.FIRST_PARTY_HARNESS.displayName} plans:`);
|
|
48
|
+
const paidPlans = data_provider_1.SKY_CODE_PLAN_KEYS.filter((plan) => plan !== 'free').map((key) => data_provider_1.SKY_CODE_PLAN_CATALOG[key]);
|
|
49
|
+
// Padded to the longest name rather than a fixed width: plan names embed the
|
|
50
|
+
// product's display name, whose length is not this renderer's to assume.
|
|
51
|
+
const nameWidth = Math.max(...paidPlans.map((plan) => plan.displayName.length)) + 1;
|
|
52
|
+
for (const plan of paidPlans) {
|
|
53
|
+
log(` ${plan.displayName.padEnd(nameWidth)} $${plan.monthlyPriceUsd}/month · ` +
|
|
50
54
|
`${(0, data_provider_1.usageMicrosToDisplayCredits)(plan.includedUsageMicros).toLocaleString()} monthly credits · ` +
|
|
51
55
|
`${(0, data_provider_1.usageMicrosToDisplayCredits)(plan.fiveHourUsageMicros).toLocaleString()} per 5 hours · ` +
|
|
52
56
|
`${plan.concurrentSessions} sessions · ${plan.requestsPerMinute} RPM`);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TSkyCodeUsageSnapshot } from '@skrr-ai/data-provider';
|
|
1
2
|
import { BaseCommand } from '../../base-command';
|
|
2
3
|
import { type RuntimeMonthlySpend } from '../../lib/harnesses';
|
|
3
4
|
/**
|
|
@@ -7,6 +8,30 @@ import { type RuntimeMonthlySpend } from '../../lib/harnesses';
|
|
|
7
8
|
* the wording is part of the observable contract and is pinned directly.
|
|
8
9
|
*/
|
|
9
10
|
export declare function renderRuntimeSpend(spend: RuntimeMonthlySpend[], log: (line: string) => void): void;
|
|
11
|
+
/**
|
|
12
|
+
* Your plan's ceilings, as lines.
|
|
13
|
+
*
|
|
14
|
+
* This screen showed the credits and the spend cap under a footer that called
|
|
15
|
+
* them "the ceiling that refuses a turn" — while the plan's monthly allowance,
|
|
16
|
+
* its five-hour window and its concurrent-session limit, each of which refuses a
|
|
17
|
+
* turn with its own message ("plan allowance is used up", "five-hour usage
|
|
18
|
+
* window is used up", "concurrent-session limit is reached"), were only on
|
|
19
|
+
* `balance usage` (OSK-4638). A refusal that names a ceiling should find that
|
|
20
|
+
* ceiling here, in the same words.
|
|
21
|
+
*
|
|
22
|
+
* The allowance is spent before the credits above; past it, overage consent
|
|
23
|
+
* decides whether the credits pay or the turn is refused. The five-hour window
|
|
24
|
+
* and the session limit are enforced together or not at all (admission needs
|
|
25
|
+
* both to be set), and what is left of the window is what admission computes:
|
|
26
|
+
* limit less used less reserved.
|
|
27
|
+
*
|
|
28
|
+
* Personal only. The workspace read does not report the workspace's overage
|
|
29
|
+
* terms, so rendering this for a workspace would state a refusal rule it cannot
|
|
30
|
+
* see.
|
|
31
|
+
*
|
|
32
|
+
* Pure so the wording is pinned directly, like `renderRuntimeSpend`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function renderPlanCeilings(usage: TSkyCodeUsageSnapshot, log: (line: string) => void, bin?: string): void;
|
|
10
35
|
/**
|
|
11
36
|
* YOUR hosted usage balance — the personal account, and only that one.
|
|
12
37
|
*
|
|
@@ -41,6 +66,13 @@ export default class BalanceShow extends BaseCommand {
|
|
|
41
66
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
42
67
|
};
|
|
43
68
|
run(): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Your plan's ceilings, beside the balance they are spent before.
|
|
71
|
+
*
|
|
72
|
+
* Best-effort, like the runtime cap below it: a failed read prints one line
|
|
73
|
+
* and leaves the balance intact rather than failing the command.
|
|
74
|
+
*/
|
|
75
|
+
private renderPlanCeilings;
|
|
44
76
|
/**
|
|
45
77
|
* The OTHER cap — the one that actually refuses a Hosted Machine.
|
|
46
78
|
*
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.renderRuntimeSpend = renderRuntimeSpend;
|
|
4
|
+
exports.renderPlanCeilings = renderPlanCeilings;
|
|
4
5
|
const core_1 = require("@oclif/core");
|
|
6
|
+
const auth_core_1 = require("@skrr-ai/auth-core");
|
|
5
7
|
const base_command_1 = require("../../base-command");
|
|
6
8
|
const balance_1 = require("../../lib/balance");
|
|
7
9
|
const workspaces_1 = require("../../lib/workspaces");
|
|
@@ -35,6 +37,52 @@ function renderRuntimeSpend(spend, log) {
|
|
|
35
37
|
}
|
|
36
38
|
}
|
|
37
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Your plan's ceilings, as lines.
|
|
42
|
+
*
|
|
43
|
+
* This screen showed the credits and the spend cap under a footer that called
|
|
44
|
+
* them "the ceiling that refuses a turn" — while the plan's monthly allowance,
|
|
45
|
+
* its five-hour window and its concurrent-session limit, each of which refuses a
|
|
46
|
+
* turn with its own message ("plan allowance is used up", "five-hour usage
|
|
47
|
+
* window is used up", "concurrent-session limit is reached"), were only on
|
|
48
|
+
* `balance usage` (OSK-4638). A refusal that names a ceiling should find that
|
|
49
|
+
* ceiling here, in the same words.
|
|
50
|
+
*
|
|
51
|
+
* The allowance is spent before the credits above; past it, overage consent
|
|
52
|
+
* decides whether the credits pay or the turn is refused. The five-hour window
|
|
53
|
+
* and the session limit are enforced together or not at all (admission needs
|
|
54
|
+
* both to be set), and what is left of the window is what admission computes:
|
|
55
|
+
* limit less used less reserved.
|
|
56
|
+
*
|
|
57
|
+
* Personal only. The workspace read does not report the workspace's overage
|
|
58
|
+
* terms, so rendering this for a workspace would state a refusal rule it cannot
|
|
59
|
+
* see.
|
|
60
|
+
*
|
|
61
|
+
* Pure so the wording is pinned directly, like `renderRuntimeSpend`.
|
|
62
|
+
*/
|
|
63
|
+
function renderPlanCeilings(usage, log, bin = 'skrr') {
|
|
64
|
+
const resets = (at) => (at ? ` — resets ${(0, balance_1.formatBalanceTimestamp)(at)}` : '');
|
|
65
|
+
const window = usage.fiveHour;
|
|
66
|
+
log('');
|
|
67
|
+
log(`${auth_core_1.FIRST_PARTY_HARNESS.displayName} ${usage.plan ?? 'current'} plan — spent before the credits, and each limit refuses a turn:`);
|
|
68
|
+
log(` Plan monthly: ${(0, balance_1.formatCreditsWithUsd)(usage.monthly.remainingUsageMicros)} left${resets(usage.monthly.resetsAt)}`);
|
|
69
|
+
if (window.limitUsageMicros > 0 && window.maxConcurrentSessions > 0) {
|
|
70
|
+
const windowLeft = Math.max(0, window.limitUsageMicros - window.usedUsageMicros - window.reservedUsageMicros);
|
|
71
|
+
log(` Plan 5-hour: ${(0, balance_1.formatCreditsWithUsd)(windowLeft)} left of ${(0, balance_1.formatCreditsWithUsd)(window.limitUsageMicros)}${resets(window.resetsAt)}`);
|
|
72
|
+
log(` Plan sessions: ${window.activeSessions} of ${window.maxConcurrentSessions} running`);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
log(' Plan 5-hour: no five-hour or concurrent-session limit');
|
|
76
|
+
}
|
|
77
|
+
log(usage.overageEnabled
|
|
78
|
+
? ' Past the plan: paid from the credits (overage on)'
|
|
79
|
+
: ` Past the plan: refused — overage is off (\`${bin} balance overage enabled\`)`);
|
|
80
|
+
if (usage.partialReasons?.includes('missing_entitlement_period')) {
|
|
81
|
+
// Catalog defaults, not this account's period: say so rather than present
|
|
82
|
+
// them as measured.
|
|
83
|
+
log(' (plan period unavailable; catalog limits shown)');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
38
86
|
/**
|
|
39
87
|
* YOUR hosted usage balance — the personal account, and only that one.
|
|
40
88
|
*
|
|
@@ -171,17 +219,40 @@ class BalanceShow extends base_command_1.BaseCommand {
|
|
|
171
219
|
else {
|
|
172
220
|
this.log(' Auto-refill: off');
|
|
173
221
|
}
|
|
222
|
+
await this.renderPlanCeilings();
|
|
174
223
|
await this.renderRuntimeSpend();
|
|
175
224
|
this.log('');
|
|
176
225
|
this.log('A credit is a micro-dollar: 1,000,000 credits = $1.00. The spend cap');
|
|
177
226
|
this.log('is a per-period ceiling, not a second balance. `skrr balance statement`');
|
|
178
227
|
this.log('itemises this same account and says what each charge was for.');
|
|
179
228
|
this.log('');
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
229
|
+
// Plural, because they are: a turn you own can be refused by the credits,
|
|
230
|
+
// the spend cap, a plan limit or a hosted runtime's monthly cap, and the
|
|
231
|
+
// refusal names which (OSK-4638).
|
|
232
|
+
this.log('These are the ceilings that refuse a turn for work you own; a refusal');
|
|
233
|
+
this.log('names the one that ran out. A session carrying a workspace is refused');
|
|
234
|
+
this.log("against the WORKSPACE's balance instead — see");
|
|
235
|
+
this.log('`skrr balance show --workspace <id>`. `skrr payments wallet` is the');
|
|
183
236
|
this.log('separate x402 crypto wallet, in USDC — not this balance.');
|
|
184
237
|
}
|
|
238
|
+
/**
|
|
239
|
+
* Your plan's ceilings, beside the balance they are spent before.
|
|
240
|
+
*
|
|
241
|
+
* Best-effort, like the runtime cap below it: a failed read prints one line
|
|
242
|
+
* and leaves the balance intact rather than failing the command.
|
|
243
|
+
*/
|
|
244
|
+
async renderPlanCeilings() {
|
|
245
|
+
let usage;
|
|
246
|
+
try {
|
|
247
|
+
usage = await (0, balance_1.getSkyCodeUsage)();
|
|
248
|
+
}
|
|
249
|
+
catch {
|
|
250
|
+
this.log('');
|
|
251
|
+
this.log(` Plan limits: unavailable (\`${this.config.bin} balance usage\` to retry)`);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
renderPlanCeilings(usage, (line) => this.log(line), this.config.bin);
|
|
255
|
+
}
|
|
185
256
|
/**
|
|
186
257
|
* The OTHER cap — the one that actually refuses a Hosted Machine.
|
|
187
258
|
*
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.renderSkyCodeUsageEvents = renderSkyCodeUsageEvents;
|
|
4
4
|
const core_1 = require("@oclif/core");
|
|
5
|
+
const auth_core_1 = require("@skrr-ai/auth-core");
|
|
5
6
|
const base_command_1 = require("../../../base-command");
|
|
6
7
|
const balance_1 = require("../../../lib/balance");
|
|
7
8
|
class BalanceUsageEvents extends base_command_1.BaseCommand {
|
|
8
|
-
static description =
|
|
9
|
+
static description = `List the ${auth_core_1.FIRST_PARTY_HARNESS.displayName} charges and run/session attribution behind aggregate allowance usage`;
|
|
9
10
|
static examples = [
|
|
10
11
|
'<%= config.bin %> balance usage events',
|
|
11
12
|
'<%= config.bin %> balance usage events --limit 20 --json',
|
|
@@ -44,7 +45,7 @@ class BalanceUsageEvents extends base_command_1.BaseCommand {
|
|
|
44
45
|
}
|
|
45
46
|
exports.default = BalanceUsageEvents;
|
|
46
47
|
function renderSkyCodeUsageEvents(events, log) {
|
|
47
|
-
log(
|
|
48
|
+
log(`${auth_core_1.FIRST_PARTY_HARNESS.displayName} usage events · ${events.ownerType} ${events.ownerId}`);
|
|
48
49
|
log(` Window ${events.from} to ${events.to}`);
|
|
49
50
|
if (events.items.length === 0) {
|
|
50
51
|
log(' No usage events in this window.');
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.renderSkyCodeUsage = renderSkyCodeUsage;
|
|
4
4
|
const core_1 = require("@oclif/core");
|
|
5
|
+
const auth_core_1 = require("@skrr-ai/auth-core");
|
|
5
6
|
const base_command_1 = require("../../base-command");
|
|
6
7
|
const balance_1 = require("../../lib/balance");
|
|
7
8
|
/**
|
|
@@ -40,7 +41,7 @@ class BalanceUsage extends base_command_1.BaseCommand {
|
|
|
40
41
|
}
|
|
41
42
|
exports.default = BalanceUsage;
|
|
42
43
|
function renderSkyCodeUsage(usage, log) {
|
|
43
|
-
log(
|
|
44
|
+
log(`${auth_core_1.FIRST_PARTY_HARNESS.displayName} ${usage.plan ?? 'current'} plan · ${usage.ownerType} ${usage.ownerId}`);
|
|
44
45
|
log(` Monthly used ${(0, balance_1.formatCreditsWithUsd)(usage.monthly.usedUsageMicros)}`);
|
|
45
46
|
log(` Monthly reserved ${(0, balance_1.formatCreditsWithUsd)(usage.monthly.reservedUsageMicros)}`);
|
|
46
47
|
log(` Monthly remaining ${(0, balance_1.formatCreditsWithUsd)(usage.monthly.remainingUsageMicros)}`);
|
|
@@ -23,8 +23,9 @@ class BrowserInstall extends core_1.Command {
|
|
|
23
23
|
async run() {
|
|
24
24
|
const { flags } = await this.parse(BrowserInstall);
|
|
25
25
|
const args = ['install'];
|
|
26
|
-
// Any spelling of the first-party harness is
|
|
27
|
-
//
|
|
26
|
+
// Any ACCEPTED spelling of the first-party harness is handed to the daemon in
|
|
27
|
+
// the wire spelling; anything else — a retired spelling included — is forwarded
|
|
28
|
+
// unchanged for the daemon's own parser to accept or refuse.
|
|
28
29
|
if (flags.harness)
|
|
29
30
|
args.push('--harness', (0, harness_provider_input_1.daemonHarnessArgument)(flags.harness));
|
|
30
31
|
if (flags.config)
|
|
@@ -23,8 +23,9 @@ class BrowserUninstall extends core_1.Command {
|
|
|
23
23
|
async run() {
|
|
24
24
|
const { flags } = await this.parse(BrowserUninstall);
|
|
25
25
|
const args = ['uninstall'];
|
|
26
|
-
// Any spelling of the first-party harness is
|
|
27
|
-
//
|
|
26
|
+
// Any ACCEPTED spelling of the first-party harness is handed to the daemon in
|
|
27
|
+
// the wire spelling; anything else — a retired spelling included — is forwarded
|
|
28
|
+
// unchanged for the daemon's own parser to accept or refuse.
|
|
28
29
|
if (flags.harness)
|
|
29
30
|
args.push('--harness', (0, harness_provider_input_1.daemonHarnessArgument)(flags.harness));
|
|
30
31
|
if (flags.config)
|
|
@@ -37,6 +37,7 @@ export default class CodeHandover extends BaseCommand {
|
|
|
37
37
|
repo: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
38
38
|
base: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
39
39
|
'allow-dirty': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
40
|
+
browser: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
40
41
|
json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
41
42
|
};
|
|
42
43
|
/** Run git, returning null rather than throwing — every caller has a fallback. */
|
|
@@ -61,6 +61,9 @@ class CodeHandover extends base_command_1.BaseCommand {
|
|
|
61
61
|
description: 'Hand over anyway when the working tree is dirty or the branch is unpushed. The cloud agent will NOT see that work.',
|
|
62
62
|
default: false,
|
|
63
63
|
}),
|
|
64
|
+
browser: core_1.Flags.boolean({
|
|
65
|
+
description: 'Give the receiving agent a browser. Refused where the deployment has no browser runtime, never run without one.',
|
|
66
|
+
}),
|
|
64
67
|
json: core_1.Flags.boolean({ description: 'Output the created task as JSON' }),
|
|
65
68
|
};
|
|
66
69
|
/** Run git, returning null rather than throwing — every caller has a fallback. */
|
|
@@ -152,6 +155,7 @@ class CodeHandover extends base_command_1.BaseCommand {
|
|
|
152
155
|
baseBranch: branch,
|
|
153
156
|
prompt,
|
|
154
157
|
machineProduct: 'hosted-job-machine',
|
|
158
|
+
...(flags.browser ? { browser: true } : {}),
|
|
155
159
|
clientRequestId: (0, node_crypto_1.randomUUID)(),
|
|
156
160
|
});
|
|
157
161
|
}
|
|
@@ -201,8 +201,9 @@ class CodeInstall extends base_command_1.BaseCommand {
|
|
|
201
201
|
async installerNote(daemonId) {
|
|
202
202
|
try {
|
|
203
203
|
const res = await (0, api_fetch_1.apiFetch)(`/api/daemons/${encodeURIComponent(daemonId)}/cli-installers`, { credential: this.resolvedCredential });
|
|
204
|
-
// Any spelling: a daemon lists the provider the way it registered it,
|
|
205
|
-
// one that predates or postdates
|
|
204
|
+
// Any accepted spelling: a daemon lists the provider the way it registered it,
|
|
205
|
+
// and during a rename's alias window one that predates or postdates the flip
|
|
206
|
+
// spells it differently.
|
|
206
207
|
const row = (res.providers ?? []).find((p) => (0, auth_core_1.isFirstPartyHarnessProvider)(p.provider));
|
|
207
208
|
const reason = row?.installDisabledReason?.trim();
|
|
208
209
|
if (!reason)
|
|
@@ -22,6 +22,7 @@ export default class CodeJobsRun extends BaseCommand {
|
|
|
22
22
|
prompt: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
23
23
|
'prompt-file': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
24
24
|
egress: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
25
|
+
browser: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
25
26
|
wait: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
26
27
|
interval: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
27
28
|
timeout: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -40,6 +40,9 @@ class CodeJobsRun extends base_command_1.BaseCommand {
|
|
|
40
40
|
description: 'Network reach. Default `isolated` — the control plane only, nothing else.',
|
|
41
41
|
options: ['isolated', 'allowlist', 'open'],
|
|
42
42
|
}),
|
|
43
|
+
browser: core_1.Flags.boolean({
|
|
44
|
+
description: 'Run the job with a browser. Refused where the deployment has no browser runtime, never run without one.',
|
|
45
|
+
}),
|
|
43
46
|
wait: core_1.Flags.boolean({ description: 'Wait for the job to finish and print its result' }),
|
|
44
47
|
interval: core_1.Flags.integer({ description: 'Poll interval in seconds while waiting', default: 5 }),
|
|
45
48
|
timeout: core_1.Flags.integer({ description: 'Give up waiting after this many minutes', default: 30 }),
|
|
@@ -88,6 +91,7 @@ class CodeJobsRun extends base_command_1.BaseCommand {
|
|
|
88
91
|
mode: 'bare',
|
|
89
92
|
machineProduct: 'hosted-job-machine',
|
|
90
93
|
...(flags.egress ? { egressPolicy: flags.egress } : {}),
|
|
94
|
+
...(flags.browser ? { browser: true } : {}),
|
|
91
95
|
clientRequestId: (0, node_crypto_1.randomUUID)(),
|
|
92
96
|
});
|
|
93
97
|
task = res?.task;
|
|
@@ -4,6 +4,7 @@ const core_1 = require("@oclif/core");
|
|
|
4
4
|
const exec_runtime_binary_1 = require("../../lib/exec-runtime-binary");
|
|
5
5
|
const daemon_binding_1 = require("../../lib/daemon-binding");
|
|
6
6
|
const daemon_installer_1 = require("../../lib/daemon-installer");
|
|
7
|
+
const daemon_setup_1 = require("../../lib/daemon-setup");
|
|
7
8
|
/**
|
|
8
9
|
* `skrr daemon install` — install the local runtime's OS service.
|
|
9
10
|
*
|
|
@@ -52,6 +53,12 @@ class DaemonInstall extends core_1.Command {
|
|
|
52
53
|
// own comment records `skrr code run -m <model>` dying the same way. Same
|
|
53
54
|
// mistake, one directory over.
|
|
54
55
|
const argv = this.argv;
|
|
56
|
+
// Before fetching anything: a machine still carrying the previous product
|
|
57
|
+
// identity's state is refused by the runtime's own install, so downloading a
|
|
58
|
+
// release first only delays the same refusal (OSK-6895).
|
|
59
|
+
if ((0, daemon_setup_1.refuseOnLegacyLocalState)((line) => this.logToStderr(line))) {
|
|
60
|
+
this.exit(1);
|
|
61
|
+
}
|
|
55
62
|
// Bootstrap only when there is nothing to forward to. An existing runtime —
|
|
56
63
|
// brew, the script installer, a dev checkout — is left exactly alone; this
|
|
57
64
|
// is a floor under the missing case, not a second update channel competing
|
|
@@ -46,6 +46,17 @@ export default class HarnessesInstall extends BaseCommand {
|
|
|
46
46
|
* reason the daemon already words. Both are answered before anything runs.
|
|
47
47
|
*/
|
|
48
48
|
private update;
|
|
49
|
+
/**
|
|
50
|
+
* Start an install or update, and survive a gateway that cut the request off.
|
|
51
|
+
*
|
|
52
|
+
* The relay holds the request while the daemon answers, and a gateway can end
|
|
53
|
+
* it first: an update returned HTTP 504 after 21.9s while the job it started
|
|
54
|
+
* ran to success, and the caller was told the outcome was unknown (OSK-10096
|
|
55
|
+
* verifier). The daemon is the only party that knows whether the request
|
|
56
|
+
* arrived, so on a server-side failure we ask it, and follow the job it
|
|
57
|
+
* started rather than reporting a result we do not have.
|
|
58
|
+
*/
|
|
59
|
+
private start;
|
|
49
60
|
/** Follow a job to its end, or report why it could not be followed (and return nothing). */
|
|
50
61
|
private follow;
|
|
51
62
|
/** What the daemon says about this provider right now, best effort. */
|
|
@@ -74,14 +74,9 @@ class HarnessesInstall extends base_command_1.BaseCommand {
|
|
|
74
74
|
await this.update(daemonId, provider, Boolean(flags.json));
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
start = await (0, cli_installers_1.startManagedCliInstall)(daemonId, provider, this.resolvedCredential);
|
|
80
|
-
}
|
|
81
|
-
catch (err) {
|
|
82
|
-
this.handleApiError(err);
|
|
77
|
+
const start = await this.start(daemonId, provider, () => (0, cli_installers_1.startManagedCliInstall)(daemonId, provider, this.resolvedCredential), Boolean(flags.json));
|
|
78
|
+
if (!start)
|
|
83
79
|
return;
|
|
84
|
-
}
|
|
85
80
|
const jobId = start.job?.id;
|
|
86
81
|
if (!start.started || !jobId) {
|
|
87
82
|
// The daemon declined and already knows why. Read its own reason off the
|
|
@@ -163,14 +158,9 @@ class HarnessesInstall extends base_command_1.BaseCommand {
|
|
|
163
158
|
});
|
|
164
159
|
return;
|
|
165
160
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
start = await (0, cli_installers_1.startManagedCliUpdate)(daemonId, provider, this.resolvedCredential);
|
|
169
|
-
}
|
|
170
|
-
catch (err) {
|
|
171
|
-
this.handleApiError(err);
|
|
161
|
+
const start = await this.start(daemonId, provider, () => (0, cli_installers_1.startManagedCliUpdate)(daemonId, provider, this.resolvedCredential), json);
|
|
162
|
+
if (!start)
|
|
172
163
|
return;
|
|
173
|
-
}
|
|
174
164
|
const jobId = start.job?.id;
|
|
175
165
|
if (!start.started || !jobId) {
|
|
176
166
|
this.log(start.alreadyRunning
|
|
@@ -199,6 +189,35 @@ class HarnessesInstall extends base_command_1.BaseCommand {
|
|
|
199
189
|
this.log((0, cli_installers_1.updateOutcomeLine)(job) ??
|
|
200
190
|
`${provider} updated${job.installedVersion ? ` to ${job.installedVersion}` : ''}.`);
|
|
201
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* Start an install or update, and survive a gateway that cut the request off.
|
|
194
|
+
*
|
|
195
|
+
* The relay holds the request while the daemon answers, and a gateway can end
|
|
196
|
+
* it first: an update returned HTTP 504 after 21.9s while the job it started
|
|
197
|
+
* ran to success, and the caller was told the outcome was unknown (OSK-10096
|
|
198
|
+
* verifier). The daemon is the only party that knows whether the request
|
|
199
|
+
* arrived, so on a server-side failure we ask it, and follow the job it
|
|
200
|
+
* started rather than reporting a result we do not have.
|
|
201
|
+
*/
|
|
202
|
+
async start(daemonId, provider, begin, json) {
|
|
203
|
+
try {
|
|
204
|
+
return await begin();
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
const status = err.status ?? 0;
|
|
208
|
+
if (status >= 500 || status === 408) {
|
|
209
|
+
const job = await (0, cli_installers_1.jobStartedDespiteTimeout)(daemonId, provider, this.resolvedCredential);
|
|
210
|
+
if (job?.id) {
|
|
211
|
+
if (!json) {
|
|
212
|
+
this.logToStderr(`The request to ${daemonId} did not come back (HTTP ${status}), but the daemon started job ${job.id}. Following it.`);
|
|
213
|
+
}
|
|
214
|
+
return { started: true, job };
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
this.handleApiError(err);
|
|
218
|
+
return undefined;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
202
221
|
/** Follow a job to its end, or report why it could not be followed (and return nothing). */
|
|
203
222
|
async follow(daemonId, jobId, verb, json) {
|
|
204
223
|
const outcome = await (0, cli_installers_1.followManagedCliInstallJob)({
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BaseCommand } from '../../base-command';
|
|
2
|
+
import { type ManagedCliProviderState } from '../../lib/cli-installers';
|
|
2
3
|
/**
|
|
3
4
|
* What each managed provider's state is on one machine.
|
|
4
5
|
*
|
|
@@ -43,3 +44,12 @@ export default class HarnessesInstallers extends BaseCommand {
|
|
|
43
44
|
*/
|
|
44
45
|
private daemonIdFor;
|
|
45
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* What each installed CLI's update story is, as sentences under the table.
|
|
49
|
+
*
|
|
50
|
+
* Sentences, not a column: an update reason is "the copy inside Devin.app
|
|
51
|
+
* updates with that app", which no column fits. Silent for a daemon that
|
|
52
|
+
* reports no update fields at all — it cannot say, and inventing "no" for it
|
|
53
|
+
* would be worse than nothing.
|
|
54
|
+
*/
|
|
55
|
+
export declare function updateNotes(providers: readonly ManagedCliProviderState[], bin: string): string[];
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.updateNotes = updateNotes;
|
|
3
4
|
const core_1 = require("@oclif/core");
|
|
4
5
|
const base_command_1 = require("../../base-command");
|
|
5
6
|
const data_provider_1 = require("@skrr-ai/data-provider");
|
|
@@ -126,6 +127,14 @@ class HarnessesInstallers extends base_command_1.BaseCommand {
|
|
|
126
127
|
for (const note of notes)
|
|
127
128
|
this.log(` ${note.provider}: ${note.detail}`);
|
|
128
129
|
}
|
|
130
|
+
// The VERSION column is where a reader asks "can I get a newer one", and
|
|
131
|
+
// the answer lived only in `--json` (OSK-10096 verifier).
|
|
132
|
+
const updateLines = updateNotes(providers, this.config.bin);
|
|
133
|
+
if (updateLines.length > 0) {
|
|
134
|
+
this.log('');
|
|
135
|
+
for (const line of updateLines)
|
|
136
|
+
this.log(` ${line}`);
|
|
137
|
+
}
|
|
129
138
|
// A provider the platform knows and this daemon did not mention. Without
|
|
130
139
|
// this it simply is not on the list, which reads as dropped support rather
|
|
131
140
|
// than as an older daemon — `devin` arrived in the 0.8.45 daemon release, so 0.8.35
|
|
@@ -177,3 +186,25 @@ class HarnessesInstallers extends base_command_1.BaseCommand {
|
|
|
177
186
|
}
|
|
178
187
|
}
|
|
179
188
|
exports.default = HarnessesInstallers;
|
|
189
|
+
/**
|
|
190
|
+
* What each installed CLI's update story is, as sentences under the table.
|
|
191
|
+
*
|
|
192
|
+
* Sentences, not a column: an update reason is "the copy inside Devin.app
|
|
193
|
+
* updates with that app", which no column fits. Silent for a daemon that
|
|
194
|
+
* reports no update fields at all — it cannot say, and inventing "no" for it
|
|
195
|
+
* would be worse than nothing.
|
|
196
|
+
*/
|
|
197
|
+
function updateNotes(providers, bin) {
|
|
198
|
+
const lines = [];
|
|
199
|
+
for (const provider of providers) {
|
|
200
|
+
if (provider.updatable === true) {
|
|
201
|
+
lines.push(`${provider.provider}: update it with \`${bin} harnesses install ${provider.provider} --update\``);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
for (const provider of providers) {
|
|
205
|
+
if (provider.updatable === false && provider.installed && provider.updateDisabledReason) {
|
|
206
|
+
lines.push(`${provider.provider}: ${provider.updateDisabledReason}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return lines;
|
|
210
|
+
}
|
|
@@ -82,6 +82,20 @@ class HarnessesLeasesShow extends base_command_1.BaseCommand {
|
|
|
82
82
|
line('Updated:', lease.updatedAt);
|
|
83
83
|
// Money last, and only when the server sent it — an absent billing block
|
|
84
84
|
// and a zero are different states.
|
|
85
|
+
//
|
|
86
|
+
// Who pays comes first. `harnesses leases billing` used to be "change who
|
|
87
|
+
// pays", so there was a way to move the payer (which never worked) and no
|
|
88
|
+
// way to read it (OSK-4628). The payer is fixed at create, and the lease
|
|
89
|
+
// carries it as `workspaceId`: the workspace account it bills, or `null`
|
|
90
|
+
// for the owner's personal account — the same scope the monthly cap below
|
|
91
|
+
// is counted in. A server that does not send the key says nothing here,
|
|
92
|
+
// because a missing field is not evidence of a personal lease.
|
|
93
|
+
if (Object.prototype.hasOwnProperty.call(lease, 'workspaceId')) {
|
|
94
|
+
const workspaceId = typeof lease.workspaceId === 'string' ? lease.workspaceId.trim() : '';
|
|
95
|
+
line('Billed to:', workspaceId
|
|
96
|
+
? `workspace ${workspaceId} (\`${this.config.bin} balance show --workspace ${workspaceId}\`)`
|
|
97
|
+
: 'your personal account');
|
|
98
|
+
}
|
|
85
99
|
line('Billing:', nested(lease.billing, 'billableState'));
|
|
86
100
|
// The monthly cap, which is what actually refuses a Hosted Machine.
|
|
87
101
|
//
|
|
@@ -421,8 +421,9 @@ class HarnessesList extends base_command_1.BaseCommand {
|
|
|
421
421
|
// mode. Materialize that default before the request so JSON cannot quietly
|
|
422
422
|
// return every historical offline row while the table shows seven live ones.
|
|
423
423
|
const status = flags.online ? 'online' : (flags.status ?? (flags.all ? undefined : 'online'));
|
|
424
|
-
// Any spelling of the first-party harness filters the same rows; the
|
|
425
|
-
// asked for the canonical one, which it matches against every
|
|
424
|
+
// Any accepted spelling of the first-party harness filters the same rows; the
|
|
425
|
+
// server is asked for the canonical one, which it matches against every
|
|
426
|
+
// accepted stored spelling.
|
|
426
427
|
const provider = flags.provider ? (0, harness_provider_input_1.canonicalHarnessInput)(flags.provider) : undefined;
|
|
427
428
|
const params = new URLSearchParams();
|
|
428
429
|
const serverStatus = serverStatusParam(status);
|
|
@@ -1,4 +1,26 @@
|
|
|
1
1
|
import { BaseCommand } from '../../base-command';
|
|
2
|
+
/** The target a `TARGET_CONFLICT` refusal names, as the API sends it. */
|
|
3
|
+
export interface ConflictingTarget {
|
|
4
|
+
id: string;
|
|
5
|
+
desiredState?: string;
|
|
6
|
+
status?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function conflictingTargetOf(body: Record<string, unknown> | undefined): ConflictingTarget | null;
|
|
9
|
+
/**
|
|
10
|
+
* What to do about a placement that already has a target, as commands.
|
|
11
|
+
*
|
|
12
|
+
* Re-running an install whose first attempt had failed printed "An unexpected
|
|
13
|
+
* error occurred. Code: TARGET_CONFLICT" (OSK-4631): no target, no path, no next
|
|
14
|
+
* step, and no word on whether the re-run had partly applied. The API now names
|
|
15
|
+
* the target in the way; this turns that into the commands for its state. A live
|
|
16
|
+
* target is changed or removed, never installed twice; one being removed can be
|
|
17
|
+
* restored, or purged once its daemon confirms cleanup.
|
|
18
|
+
*/
|
|
19
|
+
export declare function describeTargetConflict(target: ConflictingTarget, { bin, placement, created }: {
|
|
20
|
+
bin: string;
|
|
21
|
+
placement: string;
|
|
22
|
+
created: string[];
|
|
23
|
+
}): string;
|
|
2
24
|
export default class InstructionsInstall extends BaseCommand {
|
|
3
25
|
static description: string;
|
|
4
26
|
static flags: {
|